﻿#ifndef YUTOPP_TWITTER_AUTHENTICATOR_HPP
#define YUTOPP_TWITTER_AUTHENTICATOR_HPP

#include "../../../oauth/1/authenticator/basic_authenticator.hpp"
#include "policy.hpp"

#include <vector>

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/home/qi/char/char_class.hpp>

namespace webapp
{
	namespace clients
	{
		namespace twitter
		{
			//
			template<typename Protocol, typename Policy = policy::authenticator>
			class authenticator
				: public oauth::basic_authenticator<authenticator<Protocol, Policy>, Protocol, Policy>
			{
				typedef oauth::basic_authenticator<authenticator<Protocol, Policy>, Protocol, Policy>
					base_type;

				friend base_type;

				typedef typename Policy::request_token				request_token;
				typedef typename Policy::access_token				access_token;

			public:
				typedef typename base_type::auth_key_type			auth_key_type;
				typedef typename base_type::binary_type				binary_type;
				typedef typename base_type::optional_request_token	optional_request_token;
				typedef typename base_type::optional_access_token	optional_access_token;

				explicit authenticator( const auth_key_type& key )
					: base_type( key )
				{}

			private:
				optional_request_token
					parse_request_token( const binary_type& response ) const
				{
					namespace qi = boost::spirit::qi;

					std::vector<binary_type> v;

					binary_type::const_iterator begin = response.begin();
					binary_type::const_iterator end = response.end();

					const bool r = qi::phrase_parse( begin, end,
						qi::lit( "oauth_token" ) >> "="  >> +(qi::char_ - '&') >> '&'
						>> "oauth_token_secret" >> "=" >> +(qi::char_ - '&') >> '&'
						>> "oauth_callback_confirmed" >> "=" >> +qi::char_,
						boost::spirit::ascii::space,
						v
						);

					if ( r ) {
						return request_token( v.at( 0 ), v.at( 1 ) );
					} else {
						return boost::none;
					}
				}

				optional_access_token
					parse_access_token( const binary_type& response )
				{
					namespace qi = boost::spirit::qi;

					std::vector<binary_type> v;

					binary_type::const_iterator begin = response.begin();
					binary_type::const_iterator end = response.end();

					const bool r = qi::phrase_parse( begin, end,
						qi::lit( "oauth_token" ) >> "="  >> +(qi::char_ - '&') >> '&'
						>> "oauth_token_secret" >> "=" >> +(qi::char_ - '&') >> '&'
						>> "user_id" >> "=" >> +boost::spirit::ascii::digit >> '&'
						>> "screen_name" >> "=" >> +qi::char_,
						boost::spirit::ascii::space,
						v
						);

					if ( r ) {
						set_token( v.at( 0 ), v.at( 1 ) );
						return access_token( v.at( 2 ), v.at( 3 ) );
					} else {
						return boost::none;
					}
				}
			};
		} // - twitter
	} // - clients
} // - webapp

#endif /*YUTOPP_TWITTER_AUTHENTICATOR_HPP*/
